import socket
import threading
import struct
import queue

from . import StopThreading


class UdpLogic:

    def __init__(self):
        self.link_flag = False
        self.udp_socket = None
        self.udp_socket_send = None
        self.udp_socket_recv = None

        self.Multicast_address = None
        self.Target_address = None
        self.address = None

        self.recv_thread = None
        self.send_ret = -1
        self.server_th = None
        self.client_th = None

        self.command_queue = queue.Queue()
        self.flyData_queue = queue.Queue()
        self.picture_queue = queue.Queue()

    def udp_server_start(self, port) -> None:
        self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        port = int(port)
        address = ("", port)
        self.udp_socket.bind(address)
        self.sever_th = threading.Thread(target=self.udp_server_concurrency)
        self.sever_th.start()
        msg = "UDP服务端正在监听端口:{}\n".format(port)

    def udp_recv_init(self):
        ANY = '192.168.1.10'
        Multicast_address = "226.3.6.5"
        PORT = 6281
        self.udp_socket_recv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        # 允许端口复用
        self.udp_socket_recv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 绑定多播数据包的端口
        self.udp_socket_recv.bind(('', PORT))
        # 声明该socket为多播类型
        self.udp_socket_recv.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
        # 加入多播组
        self.udp_socket_recv.setsockopt(
            socket.IPPROTO_IP,
            socket.IP_ADD_MEMBERSHIP,
            socket.inet_aton(Multicast_address) + socket.inet_aton(ANY)
        )

        self.recv_thread = threading.Thread(target=self.udp_recv_concurrency)
        self.recv_thread.start()

    def udp_recv_concurrency(self) -> None:
        while True:
            try:
                recv_data, recv_addr = self.udp_socket_recv.recvfrom(1024)
                # info = recv_msg.decode("utf-8")
                msg = f"来自IP:{recv_addr[0]}端口:{recv_addr[1]}:"
                print(msg)
                if len(recv_data) == 64:
                    # TODO 数据有效性判断
                    self.flyData_queue.put(recv_data)
                elif len(recv_data) == 32:
                    self.command_queue.put(recv_data)
                elif len(recv_data) == 1024:
                    self.picture_queue.put(recv_data)


            except Exception as e:
                print(e)
                break

    def udp_server_concurrency(self) -> None:

        while True:
            try:
                recv_msg, recv_addr = self.udp_socket.recvfrom(1024)
                info = recv_msg.decode("utf-8")
                msg = f"来自IP:{recv_addr[0]}端口:{recv_addr[1]}:"
                print(msg)
                print(msg)
            except Exception as e:
                print(e)
                break

    def udp_client_start(self, ip: str, port: int) -> None:
        """
        确认UDP客户端的ip及地址
        """
        self.udp_socket_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        ttl = struct.pack('b', 1)
        self.udp_socket_send.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
        self.Target_address = (ip, port)
        msg = "UDP客户端已启动\n"

    def udp_send(self, send_info: str) -> None:
        """
        功能函数，用于UDP客户端发送消息
        """
        try:
            send_info_encoded = send_info.encode("utf-8")
            self.udp_socket_send.sendto(send_info_encoded, self.Target_address)
            msg = "UDP客户端已发送"
        except Exception as ret:
            msg = "发送失败\n"

    def udp_send_init(self):
        multicast_group = ('226.3.6.5', 6280)
        self.udp_socket_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.udp_socket_send.settimeout(10)
        ttl = struct.pack('b', 1)
        self.udp_socket_send.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)
        self.Target_address = multicast_group
        msg = "UDP客户端已启动\n"
        return self.udp_socket_send

    def udp_send_bytes(self, send_list: list) -> int:
        try:
            send_string = ''.join(item[2:] for item in send_list)
            send_data = bytes.fromhex(send_string)
            print(f"向{self.Target_address}发送了{send_data}")
            ret = self.udp_socket_send.sendto(send_data, self.Target_address)
            print(f"向{self.Target_address}发送了{ret}字节")
        except Exception as e:
            print(f"{self.Target_address}发送失败")
            raise Exception
        else:
            if ret > 0:
                self.send_ret = ret
                return ret
            return -1

    def udp_close(self) -> None:
        """
        功能函数，关闭网络连接的方法
        """
        if self.link_flag == self.ServerUDP:
            try:
                self.udp_socket.close()
                msg = "已断开网络\n"
            except Exception as ret:
                pass

            try:
                StopThreading.stop_thread(self.sever_th)
            except Exception:
                pass

        if self.link_flag == self.ClientUDP:
            try:
                self.udp_socket.close()
                msg = "已断开网络\n"
            except Exception as ret:
                pass

            try:
                StopThreading.stop_thread(self.client_th)
            except Exception:
                pass

    NoLink = -1
    ServerUDP = 2
    ClientUDP = 3
    InfoSend = 0
    InfoRec = 1
